function varargout = TLTftoolDlg(action, varargin)

% TL_SSTOOL_DLG manages user interface for TargetLink State Space Tool
%
% SYNTAX dlgInfo = tl_sstool_dlg('GetDlgInfo');
%   gets dialog info of TargetLink State Space Tool
%
%   INPUT ARGUMENTS
%   -/-
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = tl_sstool_dlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = tl_sstool_dlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = tl_sstool_dlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = tl_sstool_dlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX tl_sstool_dlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit
% $RCSfile: TLTftoolDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/ProdCodeGen/L1Scaler/Sources/MSrc/project.pj $
% $Revision: 1.8 $
% $Date: 2011/04/11 10:47:23MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action
    
    case 'GetDlgInfo'
        dlgInfo = tl_get_dlginfodefaults('tltool');
        dlgInfo.pageNames = {'Scaling'};
        dlgInfo.title     = 'Transfer Function Scaling Tool';
        varargout = {dlgInfo};
        
    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Scaling'
                [sheetDims,ctrlPos] = FcnCalcScalingControlPositions(commonGeom);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;
        
    case 'Create'
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName,dlgdata.pageNames,'exact');
        switch pageName
            case 'Scaling'
                dlgdata = FcnCreateScalingPage(pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;
        
    case 'Manage'
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');
        
        % check maskType check transfer function
        parentData = get(dlgdata.parentfig,'UserData');
        maskType  = parentData.maskType;
        [ok,msg] = FcnchkTransferFcn(dlgdata,maskType);
        if ~ok
            ds_error_msg({'You have modified the system !' ...
                msg ...
                'The Transfer Function Scaling Tool will be closed.'}, ...
                'Title','Transfer Function Scaling Tool', ...
                'PrintMessage','no', ...
                'RegisterMessage','no');
            if ishandle(dlgdata.toolfig)
                delete(dlgdata.toolfig);
            end
            delete(dlgfig);
            bModified = false;
        else
            switch pageName
                case 'Scaling'
                    [dlgdata, bModified] = FcnManageScalingPage(pageNum,dlgfig,dlgdata,pageAction);
            end
        end
        
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'SystemButtons'
        dlgfig  = varargin{1};
        dlgdata = varargin{2};
        Action  = varargin{3};
        
        bModified = false;
        
        switch Action
            case 'PlotResults'
                if ~dlgdata.toolData.bIsScaled
                    errordlg('Please perform L1-scaling procedure.','Help','modal');
                else
                    if ~ishandle(dlgdata.toolfig)
                        pageNum = 1;
                        % get data from current dialog
                        data = FcnsetPlotData(dlgdata);
                        set(dlgfig,'Pointer','watch');
                        % open plot figure
                        dlgdata.toolfig = tl_open_toolfig( ...
                            dlgdata.pageData{pageNum}.model,dlgdata.maskType,data);
                        set(dlgfig,'Pointer','arrow');
                        bModified = true;
                    else
                        figure(dlgdata.toolfig);
                    end
                end
        end
        
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'titlechange'
        toolFig = varargin{1};
        pageNum = 1;
        
        dlgdata = get(toolFig,'Userdata');
        block   = dlgdata.pageData{pageNum}.model;
        figdata.block = get_param(block,'Name');
        name = ['TargetLink: Transfer Function Scaling Tool for ''' figdata.block ''''];
        set(toolFig,'Name',name);
        
        if ishandle(dlgdata.toolfig)
            name = ['TargetLink: Worst Case Signals for ''' figdata.block ''''];
            set(dlgdata.toolfig,'Name',name);
        end
        
    case 'UpdateData'
        dlgfig  = varargin{1};
        data    = varargin{2};
        pageNum = 1;
        dlgdata = get(dlgfig,'UserData');
        dlgdata.toolData.bIsScaled = 0;
        dlgdata.toolData.bupIsScaled = 0;
        dlgdata.toolData.bloIsScaled = 0;
        dlgdata.data = data;
        dlgdata = FcnUpdateScalingPage(dlgdata,dlgfig,pageNum);
        if FcnChkOffsetAndType(dlgdata,1);
            set(dlgdata.SystemButtons.StatusLabel,'String','Ready', ...
                'ForegroundColor','k');
        end
        set(dlgfig,'Userdata',dlgdata);
        if ishandle(dlgdata.toolfig)
            FcnRefreshTFTool(dlgfig,dlgdata);
        end
        
    case 'Update' % empty case because of update of simulation plots
        dlgdata = varargin{2};
        varargout{1} = dlgdata;
        
    case 'Delete'
        dlgdata = get(gcbf,'Userdata');
        if isstruct(dlgdata) && ishandle(dlgdata.toolfig)
            delete(dlgdata.toolfig);
            dlgdata.toolfig = -1;
            set(gcbf,'Userdata',dlgdata);
        end
        
    otherwise
        error(['Invalid action "' action '"']);
        
end


%-----------------------------------------------------------------------------------------
% FcnCreateScalingPage creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateScalingPage(pageNum,dlgfig,dlgdata)

ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;

% delete function to close toolfig
set(dlgfig,'DeleteFcn','TLTftoolDlg(''Delete'');');

% save model handle in pageData
dlgdata.pageData{pageNum}.model = dlgdata.model;
dlgdata.model = -1;

% 'Output' groupbox and uicontrols
Children.scalingGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Output'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.scalingGroupbox);

Children.loConstrLabel = uicontrol( ...
    'Parent',              Children.scalingGroupbox, ...
    'Style',               'text', ...
    'String',              'lower', ...
    'Position',            ctrlPos.loConstrLabel);
Children.upConstrLabel = uicontrol( ...
    'Parent',             Children.scalingGroupbox, ...
    'Style',               'text', ...
    'String',              'upper', ...
    'Position',            ctrlPos.upConstrLabel);
Children.upL1valueLabel = uicontrol( ...
    'HorizontalAlignment', 'left', ...
    'Parent',              Children.scalingGroupbox, ...
    'Style',               'text', ...
    'Position',            ctrlPos.upL1valueLabel);
Children.loL1valueLabel = uicontrol( ...
    'HorizontalAlignment', 'left', ...
    'Parent',              Children.scalingGroupbox, ...
    'Style',               'text', ...
    'Position',            ctrlPos.loL1valueLabel);
Children.upRestvalueLabel = uicontrol( ...
    'HorizontalAlignment',   'left', ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'Position',              ctrlPos.upRestvalueLabel);
Children.loRestvalueLabel = uicontrol( ...
    'HorizontalAlignment',   'left', ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'Position',              ctrlPos.loRestvalueLabel);
Children.loImplLabel   = uicontrol( ...
    'Parent',             Children.scalingGroupbox, ...
    'Style',              'text', ...
    'String',             'lower', ...
    'Position',           ctrlPos.loImplLabel);
Children.upImplLabel    = uicontrol( ...
    'Parent',              Children.scalingGroupbox, ...
    'Style',               'text', ...
    'String',              'upper', ...
    'Position',            ctrlPos.upImplLabel);
Children.lsbScaleoptLabel = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'LSB', ...
    'Position',              ctrlPos.lsbScaleoptLabel);
Children.offScaleoptLabel = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'Offset', ...
    'Position',              ctrlPos.offScaleoptLabel);
Children.loConstrEdit  = uicontrol( ...
    'BackgroundColor',     'w', ...
    'HorizontalAlignment', 'left', ...
    'Parent',              Children.scalingGroupbox, ...
    'Style',               'edit', ...
    'Position',            ctrlPos.loConstrEdit);
Children.upConstrEdit  = uicontrol( ...
    'BackgroundColor',     'w', ...
    'HorizontalAlignment', 'left', ...
    'Parent',              Children.scalingGroupbox, ...
    'Style',               'edit', ...
    'Position',            ctrlPos.upConstrEdit);
Children.upImplvalueLabel = uicontrol( ...
    'HorizontalAlignment',   'left', ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'Position',              ctrlPos.upImplvalueLabel);
Children.loImplvalueLabel = uicontrol( ...
    'HorizontalAlignment',   'left', ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'Position',              ctrlPos.loImplvalueLabel);
Children.lsbScaleoptvalueLabel = uicontrol( ...
    'HorizontalAlignment',   'left', ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'Position',              ctrlPos.lsbScaleoptvalueLabel);
Children.offScaleoptvalueLabel = uicontrol( ...
    'HorizontalAlignment',   'left', ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'Position',              ctrlPos.offScaleoptvalueLabel);
Children.convergencevalueLabel = uicontrol( ...
    'HorizontalAlignment',    'left', ...
    'Parent',                 Children.scalingGroupbox, ...
    'Style',                  'text', ...
    'Position',               ctrlPos.convergencevalueLabel);

% scaling options text fields
Children.scalingoptLabelCons = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'Constrained limits:', ...
    'Position',              ctrlPos.scalingoptLabelCons);
Children.scalingoptLabelL1 = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'L1-scaled:', ...
    'Position',              ctrlPos.scalingoptLabelL1);
Children.scalingoptLabelRest = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'Rest term:', ...
    'Position',              ctrlPos.scalingoptLabelRest);
Children.scalingoptLabelImpl = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'Implemented limits:', ...
    'Position',              ctrlPos.scalingoptLabelImpl);
Children.scalingoptLabelScaO = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'Scaling options:', ...
    'Position',              ctrlPos.scalingoptLabelScaO);
Children.scalingoptLabelConv = uicontrol( ...
    'Parent',                Children.scalingGroupbox, ...
    'Style',                 'text', ...
    'String',                'Convergence:', ...
    'Position',              ctrlPos.scalingoptLabelConv);

% pushbutton
Children.l1ScaleButton = uicontrol( ...
    'Parent',             Children.scalingGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             'Scale', ...
    'Position',           ctrlPos.l1ScaleButton);
Children.l1ContinueButton = uicontrol( ...
    'Parent',             Children.scalingGroupbox, ...
    'Style',              'pushbutton', ...
    'String',             'Continue', ...
    'Position',           ctrlPos.l1ContinueButton);

% 'System Info' groupbox and uicontrols
Children.infoGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'System Info'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.infoGroupbox);

Children.stabilityLabel = uicontrol( ...
    'Parent',          Children.infoGroupbox, ...
    'Style',           'text', ...
    'String',          'Stability:', ...
    'Position',        ctrlPos.stabilityLabel);
Children.typeOutputsLabel = uicontrol( ...
    'Parent',          Children.infoGroupbox, ...
    'Style',           'text', ...
    'String',          'Type of outputs:', ...
    'Position',        ctrlPos.typeOutputsLabel);
Children.orderTransverfunctionLabel = uicontrol( ...
    'Parent',          Children.infoGroupbox, ...
    'Style',           'text', ...
    'String',          'System order:', ...
    'Position',        ctrlPos.orderTransverfunctionLabel);
Children.stabilityInfoLabel = uicontrol( ...
    'FontWeight',      'bold', ...
    'Parent',          Children.infoGroupbox, ...
    'Style',           'text', ...
    'Position',        ctrlPos.stabilityInfoLabel);
Children.typeOutputsInfoLabel = uicontrol( ...
    'Parent',          Children.infoGroupbox, ...
    'Style',           'text', ...
    'Position',        ctrlPos.typeOutputsInfoLabel);
Children.orderTransverfunctionInfoLabel = uicontrol( ...
    'Parent',          Children.infoGroupbox, ...
    'Style',           'text', ...
    'Position',        ctrlPos.orderTransverfunctionInfoLabel);

% 'Scaling Options' groupbox and uicontrols
Children.optionsGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Scaling Options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.optionsGroupbox);

Children.methodLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           'Scaling method:', ...
    'Position',         ctrlPos.methodLabel);
Children.convTolLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           'L1 convergence tolerance:', ...
    'Position',         ctrlPos.convTolLabel);
Children.maxRecLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           'Maximum computation time:', ...
    'Position',         ctrlPos.maxRecLabel);
Children.actRecLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           'Number of recursions:', ...
    'Position',         ctrlPos.actRecLabel);
Children.contLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           'Number of continuations:', ...
    'Position',         ctrlPos.contLabel);

Children.methodInfoLabel = uicontrol( ...
    'FontWeight',       'bold', ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           'L1-scaling', ...
    'Position',         ctrlPos.methodInfoLabel);
Children.convTolEdit = uicontrol( ...
    'BackgroundColor',  'w', ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'edit', ...
    'Position',         ctrlPos.convTolEdit);
Children.percLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           ' %', ...
    'Position',         ctrlPos.percLabel);
Children.maxTimeEdit = uicontrol( ...
    'BackgroundColor',  'w', ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'edit', ...
    'Position',         ctrlPos.maxTimeEdit);
Children.secLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'String',           ' sec', ...
    'Position',         ctrlPos.secLabel);
Children.numRecInfoLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'Position',         ctrlPos.numRecInfoLabel);
Children.contInfoLabel = uicontrol( ...
    'Parent',           Children.optionsGroupbox, ...
    'Style',            'text', ...
    'Position',         ctrlPos.contInfoLabel);

% 'Input' groupbox and uicontrols
Children.inputGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Input'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.inputGroupbox);
Children.limitsLabel   = uicontrol( ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'text', ...
    'String',            'Constrained limits:', ...
    'Position',          ctrlPos.limitsLabel);
Children.minInputLabel = uicontrol( ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'text', ...
    'String',            'lower', ...
    'Position',          ctrlPos.minInputLabel);
Children.maxInputLabel = uicontrol( ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'text', ...
    'String',            'upper', ...
    'Position',          ctrlPos.maxInputLabel);
Children.initialLabel  = uicontrol( ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'text', ...
    'String',            'Initial input:', ...
    'Position',          ctrlPos.initialLabel);
Children.initialInputLabel = uicontrol( ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'text', ...
    'String',            'u(0)', ...
    'Position',          ctrlPos.initialInputLabel);
Children.loInputEdit   = uicontrol( ...
    'BackGroundColor',   'w', ...
    'HorizontalAlignment','left', ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'edit', ...
    'Position',          ctrlPos.loInputEdit);
Children.upInputEdit   = uicontrol( ...
    'BackGroundColor',   'w', ...
    'HorizontalAlignment', 'left', ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'edit', ...
    'Position',          ctrlPos.upInputEdit);
Children.initialInputEdit = uicontrol( ...
    'BackGroundColor',   'w', ...
    'HorizontalAlignment', 'left', ...
    'Parent',            Children.inputGroupbox, ...
    'Style',             'edit', ...
    'Position',          ctrlPos.initialInputEdit);

% save all children for manage scaling page
dlgdata.pageData{pageNum}.children = Children;

% get (default) tool data from parent dialog
parentData       = get(dlgdata.parentfig,'UserData');
parentPageNum    = parentData.CurrentPageNum;
dlgdata.toolData = parentData.pageData{parentPageNum}.toolData;

% initialize toolData
dlgdata.toolData.bupIsScaled  = 0;
dlgdata.toolData.bloIsScaled  = 0;
dlgdata.toolData.bIsScaled    = 0;

% update scaling page
dlgdata = FcnUpdateScalingPage(dlgdata,dlgfig,pageNum);


%-----------------------------------------------------------------------------------------
% FcnManageScalingPage manage control actions of scaling page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageaction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageScalingPage(pageNum,dlgfig,dlgdata,pageAction)

bModified = true;
Children  = dlgdata.pageData{pageNum}.children;

switch pageAction
    
    % callbacks of uicontrols
    case {'loConstrEdit' 'upConstrEdit'}
        h = [Children.loConstrEdit ...
            Children.upConstrEdit];
        bModified = true;                                                           %#ok
        minVar    = dlgdata.data.output.min;
        maxVar    = dlgdata.data.output.max;
        if strcmp(action,'loConstrEdit')
            varStr = 'min';
            [minVarEdit,bModified] = FcnchkInput(h(1),'double');
            if ( bModified && ~all(isnan(minVarEdit)) )
                dlgdata.toolData.bloIsScaled = 0;
                if any(minVarEdit >= maxVar)
                    bModified = false;
                end
            end
        else
            varStr = 'max';
            [maxVarEdit,bModified] = FcnchkInput(h(2),'double');
            if ( bModified && ~all(isnan(maxVarEdit)) )
                dlgdata.toolData.bupIsScaled = 0;
                if any(maxVarEdit <= minVar)
                    bModified = false;
                end
            end
        end
        if bModified
            eval(['dlgdata.data.output.' varStr ' = ' varStr 'VarEdit;']);
            dlgdata.toolData.bIsScaled = 0;
        else
            fprintf('');
        end
        FcnsetCtrlFields(dlgdata,pageNum,'scalingGroupbox');
        %         bRefresh  = 1;
        
    case {'loInputEdit' 'upInputEdit'}
        h = [Children.loInputEdit ...
            Children.upInputEdit];
        bModified = true;                                                      %#ok
        minVar       = dlgdata.toolData.input.min;
        maxVar       = dlgdata.toolData.input.max;
        initialInput = dlgdata.toolData.input.initial;
        if strcmp(action,'loInputEdit')
            varStr = 'min';
            [minInput,bModified] = FcnchkInput(h(1),'double');
            if bModified
                [bModified] = FcnchkInputBounds(maxVar,minInput,initialInput,'loInputEdit');
            end
        else
            varStr = 'max';
            [maxInput,bModified] = FcnchkInput(h(2),'double');
            if bModified
                [bModified] = FcnchkInputBounds(maxInput,minVar,initialInput,'upInputEdit');
            end
        end
        if bModified
            eval(['dlgdata.toolData.input.' varStr ' = ' varStr 'Input;']);
            if dlgdata.toolData.bIsScaled
                dlgdata.data.output.min      = NaN;
                dlgdata.data.output.max      = NaN;
                dlgdata.toolData.bIsScaled   = 0;
                dlgdata.toolData.bupIsScaled = 0;
                dlgdata.toolData.bloIsScaled = 0;
                % close plot figure, if it is open
                if ishandle(dlgdata.toolfig)
                    ds_error_msg({'You have modified the input bounds !', ...
                        'The Plot figure for Worst Case Signals will', ...
                        'be closed and the scaling results will be cleared.'}, ...
                        'Title','Transfer Function Scaling Tool', ...
                        'PrintMessage','no', ...
                        'RegisterMessage','no');
                    delete(dlgdata.toolfig);
                    dlgdata.toolfig = -1;
                end
            end
        else
            fprintf('');
        end
        FcnsetCtrlFields(dlgdata,pageNum,'inputGroupbox');
        bModified = true;
        
    case 'initialInputEdit'
        oldinitialInput = dlgdata.toolData.input.initial;
        [initialInput,bModified] = FcnchkInput(Children.initialInputEdit,'double');
        % check if the value of initial input is between the input bounds
        if bModified
            u_min = dlgdata.toolData.input.min;
            u_max = dlgdata.toolData.input.max;
            [bModified] = FcnchkInputBounds(u_max,u_min,initialInput,action);
        end
        % update page
        if bModified
            dlgdata.toolData.input.initial = initialInput;
            if dlgdata.toolData.bIsScaled
                dlgdata.data.output.min      = NaN;
                dlgdata.data.output.max      = NaN;
                dlgdata.toolData.bIsScaled   = 0;
                dlgdata.toolData.bupIsScaled = 0;
                dlgdata.toolData.bloIsScaled = 0;
                % close plot figure, if it is open
                if ishandle(dlgdata.toolfig)
                    ds_error_msg({'You have modified the initial input !', ...
                        'The Plot figure for Worst Case Signals will', ...
                        'be closed and the scaling results will be cleared.'}, ...
                        'Title','Transfer Function Scaling Tool', ...
                        'PrintMessage','no', ...
                        'RegisterMessage','no');
                    delete(dlgdata.toolfig);
                    dlgdata.toolfig = -1;
                end
            end
        else
            fprintf('');
            set(gcbo,'String',sprintf('%0.3g',oldinitialInput));
        end
        FcnsetCtrlFields(dlgdata,pageNum,'inputGroupbox');
        bModified = true;
        
    case 'convTolEdit'
        % write convergence tolerance into structure
        oldConvTol = str2double(dlgdata.toolData.options.convTol);
        [convTol,bModified] = FcnchkInput(Children.convTolEdit,'double',oldConvTol);
        % check convergence tolerance
        if ( convTol < 0 || convTol >= 100 )
            bModified = false;
        end
        if bModified
            dlgdata.toolData.options.convTol = sprintf('%0.3g',convTol);
            bIsScaled = dlgdata.toolData.bIsScaled;
            if ( bIsScaled && ( convTol < oldConvTol ) )
                converge_x = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.converge_x;
                converge_x = zeros(size(converge_x));
                converge_y = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.converge_y;
                converge_y = zeros(size(converge_y));
                dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.converge_x = converge_x;
                dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.converge_y = converge_y;
            end
        else
            fprintf('');
            set(gcbo,'String',sprintf('%0.3g',oldConvTol));
        end
        
    case 'maxTimeEdit'
        % write maximum number of recursions into structure
        oldMaxTime = str2double(dlgdata.toolData.options.maxTime);
        [maxTime,bModified] = FcnchkInput(Children.maxTimeEdit,'double',oldMaxTime);
        if maxTime < 0
            bModified = false;
        end
        if bModified
            dlgdata.toolData.options.maxTime = sprintf('%0.3g',maxTime);
        else
            fprintf('');
            set(gcbo,'String',sprintf('%0.3g',oldMaxTime));
        end
        
    case {'l1ScaleButton' 'l1ContinueButton'}
        %         bL1Scale = 1;
        % get input bounds
        u_min = dlgdata.toolData.input.min;
        u_max = dlgdata.toolData.input.max;
        %         if bL1Scale
        set(dlgfig,'Pointer','watch');
        % get data
        num   = tl_resolve(dlgdata.data.num.value, dlgdata.pageData{1}.model);
        denom = tl_resolve(dlgdata.data.denom.value, dlgdata.pageData{1}.model);
        u0        = dlgdata.toolData.input.initial;
        maxTime   = evalin('base',dlgdata.toolData.options.maxTime);
        convTol   = evalin('base',[dlgdata.toolData.options.convTol '/100']);
        % check if u0 is not a number
        if isnan(u0)
            u0 = [];
        end
        % check if the transfer function is a filter
        parentData = get(dlgdata.parentfig,'UserData');
        blockType  = parentData.maskType;
        % check blocktype for l1-algorithm, because the discrete
        % state-space computation for the discrete transfer function
        % is different from the one used for the discrete filter
        switch blockType
            case 'TL_DiscreteTransferFcn'
                tfType = 'tf';
            case 'TL_DiscreteFilter'
                tfType = 'fi';
        end
        
        % invoke/continue l1-algorithm
        if strcmp(action,'l1ContinueButton')
            l1_strct_tf = dlgdata.pageData{pageNum}.l1_strct_tf;
            bIsContinue = 1;
            status_str  = 'Continue ';
        else
            l1_strct_tf = [];
            bIsContinue = 0;
            status_str  = 'Performing ';
        end
        set(dlgdata.SystemButtons.StatusLabel,'String',...
            [status_str 'L1-scaling ...'],...
            'Foreground','k');
        drawnow;
        
        % L1-Scaling function for discrete transfer function and discrete filter
        [y_min,y_max,l1_strct_tf] = tl_l1_norm_tf(num,denom,u_min,u_max,tfType,u0, ...
            [],[],maxTime,convTol,l1_strct_tf);
        if isempty([y_min' y_max'])
            return;
        end
        
        % write the output scaling parameters into structure
        dlgdata.data.output.min = y_min';
        dlgdata.data.output.max = y_max';
        
        % for following recursion
        dlgdata.toolData.bupIsScaled = 1;
        dlgdata.toolData.bloIsScaled = 1;
        dlgdata.toolData.bIsScaled   = 1;
        dlgdata.pageData{pageNum}.l1_strct_tf = l1_strct_tf;
        
        % if only gain has been scaled
        if isempty(l1_strct_tf.l1_strct)
            dlgdata.toolData.options.numRecs = 1;
        else
            dlgdata.toolData.options.numRecs = ...
                max(l1_strct_tf.l1_strct.num_recs);
            if ( all(all(l1_strct_tf.l1_strct.converge_x)) ...
                    && all(all(l1_strct_tf.l1_strct.converge_y)) )
                maxActTol = sprintf('%0.4g',l1_strct_tf.l1_strct.max_act_tol*100);
                dlgdata.toolData.options.convTol = maxActTol;
            end
        end
        if bIsContinue
            contNum = dlgdata.toolData.options.contNum;
            contNum = contNum + 1;
        else
            contNum = 0;
        end
        dlgdata.toolData.options.contNum = contNum;
        if FcnChkOffsetAndType(dlgdata,0)
            set(dlgdata.SystemButtons.StatusLabel,'String', ...
                [status_str ' L1-scaling ... done'], ...
                'ForegroundColor','k');
        end
        set(dlgfig,'Pointer','arrow');
        bModified = true;
end

if bModified
    dlgdata = FcnUpdateScalingPage(dlgdata,dlgfig,pageNum);
end


%-----------------------------------------------------------------------------------------
% FcnCalcScalingControlPositions calculates positions for all controls on scaling page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnCalcScalingControlPositions(commonGeom)

strings_and_styles = { ...
    'Constrained limits ',         'text';
    'L1-scaled',                   'text';
    '----',                        'text';
    'limits    ',                  'text';
    '123456789%',                  'text';
    'Type of outputs:',            'text';
    'FLOAT32',                     'text';
    'Scaling method:',             'text';
    'L1-scaling  ',                'text';
    'Maximum computation time',    'text';
    '123456789',                   'edit';
    '1234567',                     'text';
    'Continue',                    'pushbutton';
    ' sec',                        'text'};

[ConstrainedlimitsLabelSize, ...
    L1scaledLabelSize, ...
    stepLabelSize, ...
    limitsLabelSize, ...
    numLabelSize, ...
    infoLabelSize, ...
    numTypeLabelSize, ...
    methodLabelSize, ...
    scalingLabelSize, ...
    optionsLabelSize, ...
    recEditSize, ...
    recLabelSize, ...
    buttonSize, ...
    secLabelSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

widths = ...
    [ConstrainedlimitsLabelSize(1) stepLabelSize(1) L1scaledLabelSize(1) stepLabelSize(1) L1scaledLabelSize(1) stepLabelSize(1) ConstrainedlimitsLabelSize(1), ...
    stepLabelSize(1) ConstrainedlimitsLabelSize(1) stepLabelSize(1) ConstrainedlimitsLabelSize(1)];

[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

% textExtent = get(commonGeom.textExtent,'Extent');

%% 'Output ' groupbox and uicontrols
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + ...
    commonGeom.sheetBottomEdgeBuffer;
scalingGroupboxWidth = col(end) + ...
    colWidth(end) + ...
    commonGeom.frameSideEdgeBuffer;
scalingGroupboxHeight = ...
    1.2*recEditSize(2)+...
    2*commonGeom.editHeight + ...
    commonGeom.textHeight+...
    rowDelta+...
    commonGeom.frameTopEdgeBuffer + ...
    commonGeom.frameBottomEdgeBuffer;
ctrlPos.scalingGroupbox =  ...
    [cx cy  scalingGroupboxWidth scalingGroupboxHeight];
% upConstrLabel
cx  = col(1);
cy1 = commonGeom.frameBottomEdgeBuffer + ...
    rowDelta + ...
    commonGeom.editHeight + ...
    1.2*recEditSize(2);
ctrlPos.upConstrLabel = ...
    [cx cy1 limitsLabelSize(1) commonGeom.textHeight];
% upImplLabel
cx = col(7);
ctrlPos.upImplLabel = ...
    [cx cy1 limitsLabelSize(1) commonGeom.textHeight];
% lsbScaleoptLabel
cx = col(9);
ctrlPos.lsbScaleoptLabel = ...
    [cx cy1 limitsLabelSize(1) commonGeom.textHeight];
% loConstrLabel
cx  = col(1);
cy2 = commonGeom.frameBottomEdgeBuffer + ...
    1.2*recEditSize(2);
ctrlPos.loConstrLabel = ...
    [cx cy2 limitsLabelSize(1) commonGeom.textHeight];
% loImplLabel
cx = col(7);
ctrlPos.loImplLabel = ...
    [cx cy2 limitsLabelSize(1) commonGeom.textHeight];
% offScaleoptLabel
cx = col(9);
ctrlPos.offScaleoptLabel = ...
    [cx cy2 limitsLabelSize(1) commonGeom.textHeight];
% upConstrEdit
cx = col(1)+limitsLabelSize(1);
ctrlPos.upConstrEdit = ...
    [cx cy1 recEditSize(1) commonGeom.editHeight];
% loConstrEdit
cx = col(1)+limitsLabelSize(1);
ctrlPos.loConstrEdit = ...
    [cx cy2 recEditSize(1) commonGeom.editHeight];
% output text fields
%L1-scaledLabels
cx = col(3);
ctrlPos.upL1valueLabel = ...
    [cx cy1 recLabelSize(1) commonGeom.textHeight];
cx = col(3);
ctrlPos.loL1valueLabel = ...
    [cx cy2 recLabelSize(1) commonGeom.textHeight];
%RestLabels
cx = col(5);
ctrlPos.upRestvalueLabel = ...
    [cx cy1 numLabelSize(1) commonGeom.textHeight];
cx = col(5);
ctrlPos.loRestvalueLabel = ...
    [cx cy2 numLabelSize(1) commonGeom.textHeight];
% loImplvalueLabel
cx = col(7)+limitsLabelSize(1);
ctrlPos.loImplvalueLabel = ...
    [cx cy1 numLabelSize(1) commonGeom.textHeight];
% upImplvalueLabel
cx = col(7)+limitsLabelSize(1);
ctrlPos.upImplvalueLabel = ...
    [cx cy2 numLabelSize(1) commonGeom.textHeight];
%lsbScaleoptvalueLabel
cx = col(9)+limitsLabelSize(1);
ctrlPos.lsbScaleoptvalueLabel = ...
    [cx cy1 numLabelSize(1) commonGeom.textHeight];
% offScaleoptvalueLabel
cx = col(9)+limitsLabelSize(1);
ctrlPos.offScaleoptvalueLabel = ...
    [cx cy2 numLabelSize(1) commonGeom.textHeight];
% convergencevalueLabel
cx = col(11);
ctrlPos.convergencevalueLabel = ...
    [cx cy1 limitsLabelSize(1) commonGeom.textHeight];

% position scaling options labels
cx = col(1);
cy = cy1 + commonGeom.editHeight;
ctrlPos.scalingoptLabelCons = ...
    [cx cy  ConstrainedlimitsLabelSize(1) commonGeom.textHeight];
cx = col(3);
ctrlPos.scalingoptLabelL1 = ...
    [cx cy L1scaledLabelSize(1) commonGeom.textHeight];
cx = col(5);
ctrlPos.scalingoptLabelRest = ...
    [cx cy L1scaledLabelSize(1) commonGeom.textHeight];
cx = col(7);
ctrlPos.scalingoptLabelImpl = ...
    [cx cy ConstrainedlimitsLabelSize(1) commonGeom.textHeight];
cx = col(9);
ctrlPos.scalingoptLabelScaO = ...
    [cx cy ConstrainedlimitsLabelSize(1) commonGeom.textHeight];
cx = col(11);
ctrlPos.scalingoptLabelConv = ...
    [cx cy ConstrainedlimitsLabelSize(1) commonGeom.textHeight];

% position pushbuttons
cx = col(end) + colWidth(end)- 2*buttonSize(1)-commonGeom.sysButtonDelta;
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.l1ScaleButton = ...
    [cx cy buttonSize(1) buttonSize(2)];
cx = col(11)+colWidth(11)- buttonSize(1);
ctrlPos.l1ContinueButton = ...
    [cx cy buttonSize(1) buttonSize(2)];

% 'System Info' groupbox and uicontrols
cx = ctrlPos.scalingGroupbox(1);
cy = ctrlPos.scalingGroupbox(2) + ...
    ctrlPos.scalingGroupbox(4) + ...
    commonGeom.textHeight;
infoGroupboxWidth = 2*infoLabelSize(1) + colDelta/2;
infoGroupboxHeight = 4*rowDelta ...
    + 6*commonGeom.textHeight ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;
ctrlPos.infoGroupbox = ...
    [cx cy infoGroupboxWidth infoGroupboxHeight];

% static Labels
cx1 = col(1);
cx2 = col(1) + infoLabelSize(1) + 2*rowDelta;
cy1 = commonGeom.frameBottomEdgeBuffer ...
    + 2*(infoLabelSize(2) + 1.7*rowDelta);
for k = 2:3
    eval(['cy' num2str(k) ' = cy' num2str(k-1) ...
        ' + infoLabelSize(2) + 1.7*rowDelta;']);
end
ctrlPos.stabilityLabel                 = [cx1 cy3 infoLabelSize];
ctrlPos.stabilityInfoLabel             = [cx2 cy3 numTypeLabelSize];
ctrlPos.typeOutputsLabel               = [cx1 cy2 infoLabelSize];
ctrlPos.typeOutputsInfoLabel           = [cx2 cy2 numTypeLabelSize];
ctrlPos.orderTransverfunctionLabel     = [cx1 cy1 infoLabelSize];
ctrlPos.orderTransverfunctionInfoLabel = [cx2 cy1 numTypeLabelSize];

% 'Scaling Options' groupbox and uicontrols
cx = ctrlPos.infoGroupbox(1) ...
    + ctrlPos.infoGroupbox(3) ...
    + colDelta;
cy = ctrlPos.infoGroupbox(2);
optionsGroupboxWidth = optionsLabelSize(1) + recEditSize(1) + secLabelSize(1) + colDelta;
optionsGroupboxHeight = infoGroupboxHeight;
ctrlPos.optionsGroupbox = ...
    [cx cy optionsGroupboxWidth optionsGroupboxHeight];

% static texts and edit fields
cx = col(1);
cy1 = commonGeom.frameBottomEdgeBuffer;
for k = 2:5
    eval(['cy' num2str(k) ' = cy' num2str(k-1) ...
        ' + infoLabelSize(2) + 1.7*rowDelta;']);
end
ctrlPos.methodLabel = [cx cy5 methodLabelSize];
ctrlPos.convTolLabel = [cx cy4 optionsLabelSize];
ctrlPos.maxRecLabel = [cx cy3 optionsLabelSize];
ctrlPos.actRecLabel = [cx cy2 optionsLabelSize];
ctrlPos.contLabel = [cx cy1 optionsLabelSize];
cx = cx + optionsLabelSize(1) + 0.5*colDelta;
ctrlPos.methodInfoLabel = [cx cy5 scalingLabelSize];
ctrlPos.convTolEdit = [cx cy4 recEditSize];
ctrlPos.percLabel = [sum(ctrlPos.convTolEdit([1 3])) cy4 secLabelSize];
ctrlPos.maxTimeEdit = [cx cy3 recEditSize];
ctrlPos.secLabel = [sum(ctrlPos.convTolEdit([1 3])) cy3 secLabelSize];
ctrlPos.numRecInfoLabel = [cx cy2 recLabelSize];
ctrlPos.contInfoLabel = [cx cy1 recLabelSize];

%% 'Input' groupbox and uicontrols
% input groupbox
cx = ctrlPos.optionsGroupbox(1)+...
    ctrlPos.optionsGroupbox(3)+ ...
    colDelta;
cy = ctrlPos.infoGroupbox(2);
inputGroupboxWidth  = ctrlPos.scalingGroupbox(3)-...
    ctrlPos.optionsGroupbox(3)-...
    ctrlPos.infoGroupbox(3)-2*colDelta;
inputGroupboxHeight = infoGroupboxHeight;
ctrlPos.inputGroupbox = ...
    [cx cy inputGroupboxWidth inputGroupboxHeight];

% static texts and edit fields
cx = col(1);
for k = 2:5
    eval(['cy' num2str(k) ' = cy' num2str(k-1) ...
        ' + infoLabelSize(2) + 1.7*rowDelta;']);
end
ctrlPos.limitsLabel       = [cx cy5 ConstrainedlimitsLabelSize];
ctrlPos.maxInputLabel     = [cx cy4 limitsLabelSize];
ctrlPos.minInputLabel     = [cx cy3 limitsLabelSize];
ctrlPos.initialLabel      = [cx cy2 ConstrainedlimitsLabelSize];
ctrlPos.initialInputLabel = [cx cy1 limitsLabelSize];
cx = cx +limitsLabelSize(1);
ctrlPos.upInputEdit      = [cx cy4 recEditSize];
ctrlPos.loInputEdit      = [cx cy3 recEditSize];
ctrlPos.initialInputEdit = [cx cy1 recEditSize];

width = ...
    2*commonGeom.frameSideEdgeBuffer + ...
    scalingGroupboxWidth;

height = ...
    commonGeom.sheetTopEdgeBuffer + ...
    ctrlPos.infoGroupbox(4) + ...
    commonGeom.textHeight + ...
    ctrlPos.scalingGroupbox(4) + ...
    commonGeom.sheetBottomEdgeBuffer;

sheetDims = [width height];


%-----------------------------------------------------------------------------------------
% FcnUpdateScalingPage updates control actions of scaling page
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageNum     number of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnUpdateScalingPage(dlgdata,dlgfig,pageNum)

Children = dlgdata.pageData{pageNum}.children;

%% "System Info" groupbox
toolData = dlgdata.toolData;

%% check stability of the z-transfer function
% get numerater and denominator from dlgdata
num   = tl_resolve(dlgdata.data.num.value, dlgdata.pageData{1}.model);
denom = tl_resolve(dlgdata.data.denom.value, dlgdata.pageData{1}.model);

% check maskType for state-space computation
parentData = get(dlgdata.parentfig,'UserData');
blockType  = parentData.maskType;
switch blockType
    case 'TL_DiscreteTransferFcn'
        [Ad] = tl_tf2ss(num,denom);
    case 'TL_DiscreteFilter'
        [Ad] = tl_fi2ss(num,denom);
end
if isempty(Ad)
    stability = 'stable';
else
    eigen_vals = eig(Ad);
    mag_vals   = abs(eigen_vals);
    if all(mag_vals < 1)
        stability = 'stable';
    else
        stability = 'instable';
    end
end
set(Children.stabilityInfoLabel,'String',stability);

% check type of output
typeOutputs = dlgdata.data.output.type;
set(Children.typeOutputsInfoLabel,'String',typeOutputs);

% compute the system order
[rowAd,colAd] = size(Ad);
colAd_str = FcngetStr(colAd);
set(Children.orderTransverfunctionInfoLabel,'String',colAd_str);

% "Scaling Options" groupbox
if ( length(num) == 1 && length(denom) == 1 )% if system is a gain matrix
    enableStr = 'inactive';
    uiColor2  = get(dlgfig,'Color');
    options.convTol = [];
    options.maxTime = [];
    options.numRecs = [];
    options.contNum = [];
else
    enableStr = 'on';
    uiColor2  = [1 1 1];
    options = toolData.options;
end
set(Children.convTolEdit,'String',options.convTol, ...
    'Enable',enableStr, ...
    'BackGroundColor',uiColor2);
set(Children.maxTimeEdit,'String',options.maxTime, ...
    'Enable',enableStr, ...
    'BackGroundColor',uiColor2);
set(Children.numRecInfoLabel,'String',options.numRecs);
set(Children.contInfoLabel,'String',options.contNum);


%% "Input" groupbox edit fields
u_min = toolData.input.min;
u_max = toolData.input.max;
FcnsetCtrlFields(dlgdata,pageNum,'inputGroupbox');

%% "'Output" groupbox
% "Continue" and "Plot Results" button
bIsScaled = dlgdata.toolData.bIsScaled;
userDataPlotResults = get(dlgdata.SystemButtons.PlotResults, 'UserData');
if bIsScaled
    if isempty(dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct)  % if only gain matrix has been scaled
        enableContinueButton = 'off';
        enablePlotButton     = 'off';
        cDataPlotResults = userDataPlotResults.cDataDisabled;
        converge_x = [];
        converge_y = [];
    else
        converge_x = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.converge_x;
        converge_y = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.converge_y;
        enableContinueButton = 'on';
        enablePlotButton     = 'on';
        cDataPlotResults = userDataPlotResults.cDataEnabled;
    end
else
    enableContinueButton = 'off';
    enablePlotButton     = 'off';
    cDataPlotResults = userDataPlotResults.cDataDisabled;
end
set(Children.l1ContinueButton, 'Enable', enableContinueButton);
set(dlgdata.SystemButtons.PlotResults, ...
    'CData', cDataPlotResults, ...
    'Enable', enablePlotButton);

% "Scale" button
if ~any(isnan(u_min) | isnan(u_max))
    enablel1ScaleButton = 'on';
else
    enablel1ScaleButton = 'off';
end
set(Children.l1ScaleButton,'Enable',enablel1ScaleButton);

% "Edit" fields in scaling groupbox
FcnsetCtrlFields(dlgdata,pageNum,'scalingGroupbox');

% calculate scaling parameters and write implemented
% limits into toolData for check headroom
info.keeptype   = dlgdata.data.autoscaling.keepoutputtype;
info.keepoffset = dlgdata.data.autoscaling.keepoutputoffset;
[dlgdata.data.output, ...
    dlgdata.toolData.output.min_impl, ...
    dlgdata.toolData.output.max_impl, ...
    dlgdata.toolData.successOutputs] = FcncalcVars(dlgdata.data.output, info);
output = dlgdata.data.output;

% create info for output groupbox
% compute the rest contingent of L1-scaling and check if the
% lower constrained limits are comput by L1-norm
bloIsScaled = dlgdata.toolData.bloIsScaled;
if bloIsScaled
    if ~isempty(dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct) % if only gain matrix has been scaled
        y_min = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.y_min;
        if ( output.min == 0 || isinf(y_min) )
            Rest_min = 0;
        else
            Rest_min = 100*abs((output.min-y_min)/output.min);
        end
    else
        Rest_min  = 0;
    end
    Rest_min_str = sprintf('%0.3g',Rest_min);
    L1loScaled   = 'yes';
else
    Rest_min_str = FcngetStr(nan);
    L1loScaled   = 'no';
end
set(Children.loL1valueLabel,'String',L1loScaled)
set(Children.loRestvalueLabel,'String',[Rest_min_str ' %']);

% compute the rest contingent of L1-scaling and check if the
% lower constrained limits are comput by L1-norm
bupIsScaled = dlgdata.toolData.bupIsScaled;
if bupIsScaled
    if ~isempty(dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct) % if only gain matrix has been scaled
        y_max = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.y_max;
        if ( output.max == 0 || isinf(y_max) )
            Rest_max = 0;
        else
            y_max = dlgdata.pageData{pageNum}.l1_strct_tf.l1_strct.y_max;
            Rest_max = 100*abs((output.max-y_max)/output.max);
        end
    else
        Rest_max  = 0;
    end
    Rest_max_str = sprintf('%0.3g',Rest_max);
    L1upScaled   = 'yes';
else
    Rest_max_str = FcngetStr(nan);
    L1upScaled   = 'no';
end
set(Children.upL1valueLabel,'String',L1upScaled);
set(Children.upRestvalueLabel,'String',[Rest_max_str ' %']);

% get implemented limits
y_min_impl     = dlgdata.toolData.output.min_impl;
y_max_impl     = dlgdata.toolData.output.max_impl;
y_min_impl_str = FcngetStr(y_min_impl);
y_max_impl_str = FcngetStr(y_max_impl);

% check if LSB is arbitary
if output.arb
    lsb  = output.lsb;
    lsb_str = FcngetStr(lsb);
else
    lsb  = log2(output.lsb);
    lsb_str = ['2 ^ ' num2str(lsb)];
end
if ( isinf(lsb) ...
        || isnan(output.min) ...
        || isnan(output.max) ...
        || isnan(y_min_impl) ...
        || isnan(y_max_impl) )
    lsb_str    = FcngetStr(Inf);
    offset_str = FcngetStr(Inf);
else
    offset_str = FcngetStr(output.offset);
end
if bIsScaled
    if isempty(converge_x | converge_y)
        conv_str = '';
    else
        if all(converge_x & converge_y)
            conv_str = 'yes';
        else
            conv_str = 'no';
        end
    end
else
    conv_str = [];
end
set(Children.upImplvalueLabel,'String',y_min_impl_str);
set(Children.loImplvalueLabel,'String',y_max_impl_str);
set(Children.lsbScaleoptvalueLabel,'String',lsb_str);
set(Children.offScaleoptvalueLabel,'String',offset_str);
set(Children.convergencevalueLabel,'String',conv_str);


%-----------------------------------------------------------------------------------------
% FcnChkOffsetAndTypeAndType check conststency of scaling parameters (Offset & Datatype)
%
% INPUT ARGUMENTS
%   dlgdata         dialog data
%   msgflag         flag =1, if message should be displayed, =0 otherwise
%
% OUTPUT ARGUMENTS
%   ok              flag =1, if ok, =0 otherwise
%-----------------------------------------------------------------------------------------
function ok = FcnChkOffsetAndType(dlgdata,msgFlag)

ok = 1;

toolData = dlgdata.toolData;

typeCell = {'UInt8' 'UInt16' 'UInt32'};

% check if offset is unfrozen for UINT data type
if any(strcmp(dlgdata.data.output.type,typeCell))
    idx = find(all([~toolData.successOutputs; ...
        dlgdata.data.autoscaling.keepoutputoffset]));
    if ~isempty(idx)
        if length(idx) > 3
            idxStr = [num2str(idx(1:3)) ' ...'];
        else
            idxStr = num2str(idx);
        end
        msgStr = ['The constrained limits of y(' idxStr ')', ...
            ' cannot be implemented with unsigned data type' ...
            ' and frozen offset !'];
        if msgFlag
            ds_error_msg(msgStr, ...
                'Title','Transfer Function Scaling Tool', ...
                'PrintMessage','no', ...
                'RegisterMessage','no');
        end
        set(dlgdata.SystemButtons.StatusLabel,'String',msgStr, ...
            'ForegroundColor','r');
        ok = 0;
    end
end


%-----------------------------------------------------------------------------------------
% FcnchkInput checks string of edit field
%
% INPUT ARGUMENTS
%   h           handle of edit control
%   entryType   type
%   defaultVal  default value
%
% OUTPUT ARGUMENTS
%   inputVal    value
%   ok          flag =1, if ok, =0 otherwise
%-----------------------------------------------------------------------------------------
function [inputVal,ok] = FcnchkInput(h,entryType,defaultVal)

inputValStr = get(h,'String');
if nargin < 3
    defaultVal = [];
end

ok = 1;

switch entryType
    
    case 'double'
        if isempty(inputValStr) ...
                || (isa(inputValStr,'char') && strcmp(inputValStr,''))
            inputVal = NaN;
        else
            inputVal = str2double(inputValStr);
            if ( ~isa(inputVal,'double') ...
                    || isempty(inputVal) ...
                    || length(inputVal) > 1 ...
                    || isinf(inputVal) ...
                    || isnan(inputVal) ...
                    || ~isreal(inputVal) )
                inputVal = defaultVal;
                ok = 0;
            end
        end
        
end


%-----------------------------------------------------------------------------------------
% FcnchkInput checks inputs of input groupbox, respectively the bounds
%
% INPUT ARGUMENTS
%   u_max           maximum of input
%   u_min           minimum of input
%   initialInput    initial input
%   action  default value
%
% OUTPUT ARGUMENTS
%   inputVal    value
%   bModified   flag =1, if modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [bModified] = FcnchkInputBounds(u_max,u_min,initialInput,action)

switch action
    case 'loInputEdit'
        if ( (~isnan(u_max) && u_min > u_max) ...
                || (~isnan(initialInput) && u_min > initialInput) )
            bModified = false;
        else
            bModified = true;
        end
        
    case 'upInputEdit'
        if ( (~isnan(u_min) && u_max < u_min) ...
                || (~isnan(initialInput) && u_max < initialInput) )
            bModified = false;
        else
            bModified = true;
        end
        
    case 'initialInputEdit'
        if ( (~isnan(u_max) && initialInput > u_max) ...
                || (~isnan(u_min) && initialInput < u_min) )
            bModified = false;
        else
            bModified = true;
        end
end


%--------------------------------------------------------------------------
% FcngetStr get formated strings for listbox
%
% INPUT ARGUMENTS
%   num         value
%
% OUTPUT ARGUMENTS
%   num_str     string
%--------------------------------------------------------------------------
function num_str = FcngetStr(num)

num_str = sprintf('%0.3g',num);
if ~isfinite(num)
    num_str = '--- ';
end


%-----------------------------------------------------------------------------------------
% FcnsetCtrlFields writes data into edit fields
%
% INPUT ARGUMENTS
%   dlgdata         current dialog data
%   pageNum         page number
%   groupboxStr     current groupbox data
%
% OUTPUT ARGUMENTS
%   - / -
%-----------------------------------------------------------------------------------------
function  FcnsetCtrlFields(dlgdata,pageNum,groupboxStr)

Children  = dlgdata.pageData{pageNum}.children;

switch groupboxStr
    case 'scalingGroupbox'
        colorStr = 'k';
        y_min = dlgdata.data.output.min;
        y_max = dlgdata.data.output.max;
        if ( isnan(y_min) || isinf(y_min) )
            min_str = [];
        else
            min_str = FcngetStr(y_min);
        end
        if ( isnan(y_max) || isinf(y_max) )
            max_str = [];
        else
            max_str = FcngetStr(y_max);
        end
        set(Children.loConstrEdit,'String',min_str,'ForeGroundColor',colorStr);
        set(Children.upConstrEdit,'String',max_str,'ForeGroundColor',colorStr);
        
    case 'inputGroupbox'
        colorStr = 'k';
        u_min = dlgdata.toolData.input.min;
        u_max = dlgdata.toolData.input.max;
        u0    = dlgdata.toolData.input.initial;
        if ( isnan(u_min) || isinf(u_min) )
            min_str = [];
        else
            min_str = FcngetStr(u_min);
        end
        if ( isnan(u_max) || isinf(u_max) )
            max_str = [];
        else
            max_str = FcngetStr(u_max);
        end
        if ( isnan(u0) || isinf(u0) )
            initial_str = [];
        else
            initial_str = FcngetStr(u0);
        end
        set(Children.loInputEdit,'String',min_str,'ForeGroundColor',colorStr);
        set(Children.upInputEdit,'String',max_str,'ForeGroundColor',colorStr);
        set(Children.initialInputEdit,'String',initial_str,'ForeGroundColor',colorStr);
end


%--------------------------------------------------------------------------
% FcncalcVars calculate implemented limits, lsb's and offsets
%
% INPUT ARGUMENTS
%   data        data set of variable
%   info        keep information
%
% OUTPUT ARGUMENTS
%   data        modified data set of variable
%   min_impl    vector of minima
%   max_impl    vector of maxima
%   success     success vector
%--------------------------------------------------------------------------
function [data,min_impl,max_impl,success] = FcncalcVars(data, info)

% output is always scalar with width = 1
scData.min    = data.min;
scData.max    = data.max;
scData.arb    = data.arb;
scData.offset = data.offset;
scData.lsb    = data.lsb;
scData.type   = data.type;
scData.simmin = NaN;
scData.simmax = NaN;
[scData,success] = tl_scale(scData, 0, info);
if success
    [maxint,minint] = tl_int_bounds(scData.type);
    offset   = scData.offset;
    lsb      = scData.lsb;
    min_impl = lsb * minint + offset;
    max_impl = lsb * maxint + offset;
else
    min_impl = NaN;
    max_impl = NaN;
    offset   = data.offset;
    lsb      = data.lsb;
end
%      intMax = ceil((data.max(i) - offset(i)) / lsb(i));
%      intMin = floor((data.min(i) - offset(i)) / lsb(i));
%      data.max(i) = lsb(i)*intMax + offset(i);
%      data.min(i) = lsb(i)*intMin + offset(i);

data.lsb    = lsb;
data.offset = offset;


%-----------------------------------------------------------------------------------------
% FcnchkTransferFcn check transfer function
%
% INPUT ARGUMENTS
%   dlgdata         current dialog data
%   masktype        masktype of current block
%
% OUTPUT ARGUMENTS
%   ok              flag =1, if ok, =0 otherwise
%   msg             error message
%-----------------------------------------------------------------------------------------
function [ok,msg] = FcnchkTransferFcn(dlgdata,maskType)

ok = 1;                                                                     %#ok
msg = [];

%% check numerater and denominator
try
    num = tl_resolve(dlgdata.data.num.value, dlgdata.pageData{1}.model);
    den = tl_resolve(dlgdata.data.denom.value, dlgdata.pageData{1}.model);
catch
    msg = ['Transfer function could not be evaluated: ' lasterr];
    ok = 0;
    return;
end
if ( isempty(num) ...
        || isempty(den) )
    msg = 'Numerator or denominator must not be empty, respectively !';
    ok = 0;
    return;
end
[num,ok] = ds_check_value(num,'double vector');
if ~ok
    msg = 'Numerator must be a real row vector !';
    ok = 0;
    return;
end
if size(num,1) ~= 1
    msg = 'Numerator must be a row vector !';
    ok = 0;
    return;
end
[den,ok] = ds_check_value(den,'double vector');
if ~ok
    msg = 'Denominator must be a real row vector !';
    ok = 0;
    return;
end
% check if first element of denominator is zero
if length(den) == 1
    if den == 0
        msg = 'Denominator must not be zero !';
        ok = 0;
        return;
    end
else
    if den(1) == 0
        msg = 'First element of the denominator must not be zero !';
        ok = 0;
        return;
    end
    if size(den,1) ~= 1
        msg = 'Denominator must be a row vector !';
        ok = 0;
        return;
    end
end

% get dimensions of numerator and denominator
m = length(num);
% check if the first elements of denominator are zero, eliminate
% the first zeros until to the first element noneqal zero
switch maskType
    case 'TL_DiscreteTransferFcn'
        i = 1;
        while den(i) == 0
            i = i + 1;
        end
        den = den(i:end);
        % get size of denominator
        n = length(den);
        % check for proper numerator
        if m > n
            % try to strip leading zeros to make proper
            if ~(all(all(num(1:(m-n)) == 0)))
                msg = 'Denominator must be higher or equal order than numerator.';
                ok = 0;
                return;
            end
        end
        % check stability of the z-transfer function
        [Ad] = tl_tf2ss(num,den);
        eigen_vals = eig(Ad);
        mag_vals   = abs(eigen_vals);
        if any(mag_vals >= 1)
            msg = ['The transfer function has to be stable to ', ...
                'use the Transfer Function Scaling Tool.'];
            ok = 0;
            return;
        end
    case 'TL_DiscreteFilter'
        % check stability of the filter
        [Ad] = tl_fi2ss(num,den);
        eigen_vals = eig(Ad);
        mag_vals   = abs(eigen_vals);
        if any(mag_vals >= 1)
            msg = ['The transfer function has to be stable to ', ...
                'use the Transfer Function Scaling Tool.'];
            ok = 0;
            return;
        end
end


%-----------------------------------------------------------------------------------------
% FcnsetPlotData prepares structure for plot figure
%
% INPUT ARGUMENTS
%   dlgdata         current dialog data
%
% OUTPUT ARGUMENTS
%   data            plot data
%-----------------------------------------------------------------------------------------
function data = FcnsetPlotData(dlgdata)

% get scaling data for plot figure
% get input bounds
data.input.min = dlgdata.toolData.input.min;
data.input.max = dlgdata.toolData.input.max;

% get constrained limits
dlgdata.output.min = dlgdata.data.output.min;
dlgdata.output.max = dlgdata.data.output.max;

% calculate implementet limits, lsb and offset
info.keeptype   = dlgdata.data.autoscaling.keepoutputtype;
info.keepoffset = dlgdata.data.autoscaling.keepoutputoffset;
[data.output,y_min_impl,y_max_impl] = FcncalcVars(dlgdata.data.output,info);
data.output.min_impl = y_min_impl;
data.output.min_impl = y_max_impl;
data.output.type     = dlgdata.data.output.type;
data.numOutputs      = dlgdata.data.output.width;
data.l1_strct_tf     = dlgdata.pageData{1}.l1_strct_tf;
data.options         = dlgdata.toolData.options;


%-----------------------------------------------------------------------------------------
% FcnRefreshTFTool refreshs tftool plot figure window
%
% INPUT ARGUMENTS
%   dlgfig          current dialog handle
%   dlgdata         current dialog data
%
% OUTPUT ARGUMENTS
%   - / -
%-----------------------------------------------------------------------------------------
function FcnRefreshTFTool(dlgfig,dlgdata)

pageNum = 1;
toolfig = dlgdata.toolfig;

if ishandle(toolfig)
    set(dlgfig,'Pointer','watch');
    data = FcnsetPlotData(dlgdata);
    name = get_param(dlgdata.pageData{pageNum}.model,'Name');
    tl_tftool('refresh',data,name,toolfig);
    set(dlgfig,'Pointer','arrow');
end
